package com.avalonsql.core;

import com.avalonsql.core.configs.ConfigIOException;
import com.avalonsql.core.configs.ConnectionConfig;
import com.avalonsql.core.db.DBException;
import com.avalonsql.core.db.DBManager;
import com.avalonsql.core.db.connection.ConnectionProperties;
import com.avalonsql.core.db.connection.ConnectionWrapper;
import com.avalonsql.core.db.managers.DefaultProvidersFactory;
import com.avalonsql.core.db.managers.api.IDBObjectsManager;
import com.avalonsql.core.db.managers.api.IProvidersFactory;
import com.avalonsql.core.db.objects.api.IRootObject;
import com.avalonsql.core.db.objects.impl.*;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Collection;

public class DBClient {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, DBException, IOException, SQLException, ConfigIOException {
        IProvidersFactory providersFactory  = new DefaultProvidersFactory();

        ConnectionConfig connectionConfig = (ConnectionConfig) new ConnectionConfig("config/connections/SQLServer.xml").reload();
        ConnectionWrapper connectionWrapper = DBManager.addConnection(connectionConfig);
        ConnectionProperties connectionProperties = connectionWrapper.getConnectionProperties();

//        DBManager.executeUpdate(connectionWrapper.getConnection(), "CREATE VIEW view_test AS SELECT * FROM TEST");

//        ResultSet rs = connectionWrapper.getConnection().getMetaData().getTableTypes();
//        while(rs.next()) {
//        	System.out.println(getStringValue(rs, "TABLE_TYPE"));
//        }
        

        Collection<Catalog> rootObjects = providersFactory.getRootObjectsManager(connectionWrapper, Catalog.class).loadAll();

        
        
        IDBObjectsManager<StringFunction, IRootObject> stringFunctionsManager = providersFactory.getDBObjectsManager(connectionWrapper, StringFunction.class);
        IDBObjectsManager<SystemFunction, IRootObject> systemFunctionsManager = providersFactory.getDBObjectsManager(connectionWrapper, SystemFunction.class);
        IDBObjectsManager<NumericFunction, IRootObject> numericFunctionsManager = providersFactory.getDBObjectsManager(connectionWrapper, NumericFunction.class);
        IDBObjectsManager<TimeDateFunction, IRootObject> timeDateFunctionsManager = providersFactory.getDBObjectsManager(connectionWrapper, TimeDateFunction.class);
        
        IDBObjectsManager<Table, IRootObject> tablesManager = providersFactory.getDBObjectsManager(connectionWrapper, Table.class);
        IDBObjectsManager<TableColumn, Table> tableColumnsManager = providersFactory.getDBObjectsManager(connectionWrapper, TableColumn.class);
        IDBObjectsManager<View, IRootObject> viewsManager = providersFactory.getDBObjectsManager(connectionWrapper, View.class);
        IDBObjectsManager<ViewColumn, View> viewColumnsManager = providersFactory.getDBObjectsManager(connectionWrapper, ViewColumn.class);
        IDBObjectsManager<IndexKey, Table> indexKeysManager = providersFactory.getDBObjectsManager(connectionWrapper, IndexKey.class);
        IDBObjectsManager<IndexKeyColumn, IndexKey> indexKeyColumnsManager = providersFactory.getDBObjectsManager(connectionWrapper, IndexKeyColumn.class);
        IDBObjectsManager<PrimaryKey, Table> primaryKeysManager = providersFactory.getDBObjectsManager(connectionWrapper, PrimaryKey.class);
        IDBObjectsManager<PrimaryKeyColumn, PrimaryKey> primaryKeyColumnsManager = providersFactory.getDBObjectsManager(connectionWrapper, PrimaryKeyColumn.class);
        IDBObjectsManager<UniqueKey, Table> uniqueKeysManager = providersFactory.getDBObjectsManager(connectionWrapper, UniqueKey.class);
        IDBObjectsManager<UniqueKeyColumn, UniqueKey> uniqueKeyColumnsManager = providersFactory.getDBObjectsManager(connectionWrapper, UniqueKeyColumn.class);
        IDBObjectsManager<StoredProcedure, IRootObject> storedProcedureManager = providersFactory.getDBObjectsManager(connectionWrapper, StoredProcedure.class);
        IDBObjectsManager<StoredProcedureColumn, StoredProcedure> storedProcedureColumnsManager = providersFactory.getDBObjectsManager(connectionWrapper, StoredProcedureColumn.class);

        for (IRootObject rootObject : rootObjects) {
            System.out.println(rootObject);

            connectionProperties.setCatalog(rootObject.getName());

            System.out.println("String functions........................");
            for (StringFunction function : stringFunctionsManager.loadAll(rootObject)) {
            	System.out.println(function);
            }

            System.out.println("Numeric functions........................");
            for (NumericFunction function : numericFunctionsManager.loadAll(rootObject)) {
            	System.out.println(function);
            }

            System.out.println("Time Date functions........................");
            for (TimeDateFunction function : timeDateFunctionsManager.loadAll(rootObject)) {
            	System.out.println(function);
            }

            System.out.println("System functions........................");
            for (SystemFunction function : systemFunctionsManager.loadAll(rootObject)) {
            	System.out.println(function);
            }


            Collection<Table> tables = tablesManager.loadAll(rootObject);
            for (Table table : tables) {
                System.out.println("\tT: " + table);
                Collection<TableColumn> tableColumns = tableColumnsManager.loadAll(table);
                for (TableColumn tableColumn : tableColumns) {
                    System.out.println("\t\t" + tableColumn);
                }

                Collection<PrimaryKey> primaryKeys = primaryKeysManager.loadAll(table);
                for (PrimaryKey primaryKey : primaryKeys) {
                    System.out.println("\t\tPK: " + primaryKey);
                    Collection<PrimaryKeyColumn> primaryKeyColumns = primaryKeyColumnsManager.loadAll(primaryKey);
                    for (PrimaryKeyColumn primaryKeyColumn : primaryKeyColumns) {
                        System.out.println("\t\t\t" + primaryKeyColumn);
                    }
                }
//            }

            Collection<UniqueKey> uniqueKeyKeys = uniqueKeysManager.loadAll(table);
                for (UniqueKey uniqueKey : uniqueKeyKeys) {
                    System.out.println("\t\tU: " + uniqueKey);
                    Collection<UniqueKeyColumn> uniqueKeyColumns = uniqueKeyColumnsManager.loadAll(uniqueKey);
                    for (UniqueKeyColumn uniqueKeyColum : uniqueKeyColumns) {
                        System.out.println("\t\t\t" + uniqueKeyColum);
                    }
                }
//            }

        Collection<IndexKey> indexKeys = indexKeysManager.loadAll(table);
                for (IndexKey indexKey : indexKeys) {
                    System.out.println("\t\tI: " + indexKey);
                    Collection<IndexKeyColumn> indexKeyColumns = indexKeyColumnsManager.loadAll(indexKey);
                    for (IndexKeyColumn indexKeyColumn : indexKeyColumns) {
                        System.out.println("\t\t\t" + indexKeyColumn);
                    }
                }
//            }
            }
			Collection<View> views = viewsManager.loadAll(rootObject);
            for (View view : views) {
                System.out.println("\tV: " + view);
                Collection<ViewColumn> viewColumns = viewColumnsManager.loadAll(view);
                for (ViewColumn viewColumn : viewColumns) {
                    System.out.println("\t\t" + viewColumn);
                }
            }
            Collection<StoredProcedure> storedProcedures = storedProcedureManager.loadAll(rootObject);
            for (StoredProcedure storedProcedure : storedProcedures) {
                System.out.println("\tSP: " + storedProcedure);
                Collection<StoredProcedureColumn> storedProcedureColumns = storedProcedureColumnsManager.loadAll(storedProcedure);
                for (StoredProcedureColumn storedProcedureColumn : storedProcedureColumns) {
                    System.out.println("\t\t" + storedProcedureColumn);
                }
            }
        }
    }
}
